#ifndef _UDP_SERVER_HPP
#define _UDP_SERVER_HPP

#include <iostream>
#include <string>
#include <memory>
#include <strings.h>
#include <functional>
// zdl:: 网络头文件必加
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "common.hpp"
#include "inetAddr.hpp"
#include "Log.hpp"
#include "Mutex.hpp"
#include <cstring>
#include "dictionary.hpp"
const static int gsockfd = -1;
const static std::string gdefaultip = "127.0.0.1"; // 表示本地机器
const static uint16_t fdefaultport = 8080;
using namespace LogMudule;

using func_t = std::function<std::string(const std::string &)>;
class udpServer
{
private:
    int _sockfd;
    uint16_t _port;
    // std::string _ip ; // 服务器对应的ip
    inetAddr _addr;
    bool _is_running;
    // 业务就是使用相应的回调函数来完成的，整个服务器不需要观念更新数据的处理，就只需要进行网络的io就够了
    func_t _func;

public:
    udpServer(
        const func_t &func, const uint16_t &port = fdefaultport)
        : _sockfd(gsockfd), _addr(port), _func(func),
          _is_running(false)
    {
        // initServer();
    }
    ~udpServer()
    {
        if (_sockfd > gsockfd)
            ::close(_sockfd);
    }

    void initServer()
    {
        _sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            LOG(LogLevel::FATAL) << "socket" << strerror(errno);
            die(socket_error);
        }
        // 2.
        LOG(LogLevel::INFO) << "socket success, socket is : " << _sockfd;
        //         // 2.填充网络信息, 并进行bind绑定
        //         struct sockaddr_in local;
        // // zdl:: 在进行操作时，需要将这个local全清0
        //         bzero(&local, sizeof(local));
        //         local.sin_family = AF_INET;
        //         local.sin_port = htons(_port); // 在进行数据的传递时需要将ip发生红岛网络中
        //         // local.sin_addr.s_addr = ::inet_addr(_ip.c_str()); // 1.string ip -> 4 bytes 2. network order
        //         local.sin_addr.s_addr = INADDR_ANY;

        // 2.1 bind
        int n = ::bind(_sockfd, _addr.netAdddr(), _addr.netAddrLen());
        if (n < 0)
        {
            LOG(LogLevel::FATAL) << "socket" << strerror(errno);
            die(bind_error);
        }
        LOG(LogLevel::INFO) << "bind success, socket is : " << _sockfd;

        // 到目前为止都还没有将信息发生到内核中
    }
    void start()
    {
        _is_running = 1;
        while (true)
        {

            char inbuffer[1024]; // string
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t n = ::recvfrom(_sockfd, inbuffer,
                                   sizeof(inbuffer) - 1, 0, conv(&peer), &len);
            if (n > 0)
            {
                // 1. 消息内容 && 2. 谁发给我的
                // uint16_t clientport = peer.sin_port;
                // std::string clientip = ::inet_ntoa(peer.sin_addr);
                // inetAddr cli(peer);
                // std::string clientinfo = cli.ip() + ":" + std::to_string(cli.port()) + " # " + inbuffer;
                // LOG(LogLevel::DEBUG) << clientinfo;

                // std::string echo_string = "echo#";
                // echo_string += inbuffer;
                // 把英文单词转换为中文
                inbuffer[n] = 0;
                std::string ret = _func(inbuffer);
                ::sendto(_sockfd, ret.c_str(), ret.size(), 0, conv(&peer), sizeof(peer));
            }
        }
        _is_running = false;
    }
};

#endif // !_UDP_SERVER_HPP